home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / vroom / vtc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.1 KB  |  534 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*------------------------------------------------------------------------------
  18.  * Vroom Track Compiler
  19.  *----------------------------------------------------------------------------*/
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <strings.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <fcntl.h>
  28. #include <math.h>
  29.  
  30.  
  31. #define    STRAIGHT_TRACK        (0)
  32. #define    L_CURVE_TRACK        (1)
  33. #define    R_CURVE_TRACK        (2)
  34. #define    MERGE_IN_TRACK        (3)
  35. #define    MERGE_OUT_TRACK        (4)
  36. #define    MERGE_TRACK        MERGE_IN_TRACK
  37. #define    MAX_COURSE_SIZE        (150)
  38. #define    OPTIMAL_STRAIGHT_LENGTH    (800.0f)
  39. #define    MINIMAL_STRAIGHT_LENGTH    (0.75f*OPTIMAL_STRAIGHT_LENGTH)
  40. #define    MIN_RADIUS        (300.0f)
  41. #define    LANE_WIDTH        (75.0f)
  42.  
  43.  
  44. typedef struct {
  45.     char        id[4] ;
  46.     float        data[8] ;
  47.     } TrackDetailQuad ;
  48.  
  49.  
  50. /* BEGIN PROTOTYPES -S vtc.c */
  51. static void     addCurvedTrack( int token, int nLanes, float angle,
  52.                     float radius ) ;
  53. static void     addMergeInTrack( int nLanes, float length ) ;
  54. static void     addMergeOutTrack( int nLanes, float length ) ;
  55. static void     addStraightTrack( int nLanes, float length ) ;
  56. static void     addTrackToken( int token, float arg1, float arg2 ) ;
  57. static void     checkLanes( int nLanes ) ;
  58. static void     compileTrack( char *inName, char *outName ) ;
  59. static void     myWrite( int fd, void *p, int size ) ;
  60. /* END PROTOTYPES -S vtc.c */
  61.  
  62.  
  63. static TrackDetailQuad    details[MAX_COURSE_SIZE/4] ;
  64.  
  65.  
  66.  
  67. static char    *trackNames[] = {
  68.             "STRAIGHT_TRACK",
  69.             "L_CURVE_TRACK",
  70.             "R_CURVE_TRACK",
  71.             "MERGE_TRACK",
  72.             } ;
  73. static int    trackNameSize[] = {
  74.             14,
  75.             13,
  76.             13,
  77.             11,
  78.             } ;
  79.  
  80. static char    *basename ;
  81. static int    nTrack = 0 ;
  82. static int    lastNLanes ;
  83. static int    nLine = 0 ;
  84.  
  85. int
  86. main(
  87.     int    argc,
  88.     char    **argv
  89.     )
  90. {
  91.     /*
  92.      * Get basename.
  93.      */
  94.     if( ( basename = strrchr( argv[0], '/' ) ) == NULL )
  95.         basename = argv[0] ;
  96.     else
  97.         basename++ ;
  98.  
  99.     if( argc != 3 )
  100.     {
  101.         fprintf( stderr, "Usage: %s track_src out_track.vct\n",
  102.             basename ) ;
  103.         exit( 1 ) ;
  104.     }
  105.  
  106.     compileTrack( argv[1], argv[2] ) ;
  107.  
  108.     exit( 0 ) ;
  109. }
  110.  
  111.  
  112.  
  113. /*------------------------------------------------------------------------------
  114.  * Compile an ascii track description into an optimized binary one.
  115.  *----------------------------------------------------------------------------*/
  116. static void
  117. compileTrack(
  118.     char    *inName,
  119.     char    *outName
  120.     )
  121. {
  122.     FILE    *in ;
  123.     int    out ;
  124.     int    i ;
  125.     int    n ;
  126.     char    line[256] ;
  127.     int    nLaps ;
  128.     int    nLanes ;
  129.     float    length ;
  130.     float    angle ;
  131.     float    radius ;
  132.  
  133.     if( ( in = fopen( inName, "r" ) ) == NULL )
  134.     {
  135.         fprintf( stderr, "%s: could not open %s\n", basename, inName ) ;
  136.         exit( 1 ) ;
  137.     }
  138.  
  139.     if( ( out = open( outName, O_WRONLY | O_CREAT | O_TRUNC, 0644 ) ) < 0 )
  140.     {
  141.         perror( basename ) ;
  142.         exit( 1 ) ;
  143.     }
  144.  
  145.     do {
  146.         if( fgets( line, sizeof( line ), in ) == NULL )
  147.         {
  148.             perror( inName ) ;
  149.         }
  150.         nLine++ ;
  151.     } while( line[0] == '#' ) ;
  152.  
  153.     nLaps = atoi( line ) ;
  154.  
  155.     if( nLaps < 0 || nLaps > 99 )
  156.     {
  157.         fprintf( stderr, "%s: number of laps must be between 1 and 99,"
  158.                 " inclusive\n", basename ) ;
  159.         exit( 1 ) ;
  160.     }
  161.  
  162.     myWrite( out, &nLaps, sizeof( nLaps ) ) ;
  163.  
  164.     while( fgets( line, sizeof( line ), in ) != NULL )
  165.     {
  166.         nLine++ ;
  167.         if( line[0] == '#' )
  168.         {
  169.             continue ;
  170.         }
  171.  
  172.         for( i = 0 ; i < sizeof( trackNames ) / sizeof( trackNames[0] );
  173.             i++ )
  174.         {
  175.             if( !strncmp( line, trackNames[i], trackNameSize[i] ) )
  176.                 break ;
  177.         }
  178.  
  179.         if( nTrack == 0 && i != STRAIGHT_TRACK )
  180.         {
  181.             fprintf( stderr, "%s: first track piece must be a "
  182.                 "straight piece\n", basename ) ;
  183.             exit( 1 ) ;
  184.         }
  185.  
  186.         switch( i )
  187.         {
  188.             case STRAIGHT_TRACK :
  189.                 if( sscanf( line, "%*s %d %f", &nLanes,
  190.                     &length ) != 2 )
  191.                 {
  192.                     fprintf( stderr, "%s: error reading "
  193.                         "line %d of %s\n", basename,
  194.                         nLine, inName ) ;
  195.                     exit( 1 ) ;
  196.                 }
  197.                 addStraightTrack( nLanes, length ) ;
  198.                 break ;
  199.  
  200.             case MERGE_TRACK :
  201.                 if( sscanf( line, "%*s %d %f", &nLanes,
  202.                     &length ) != 2 )
  203.                 {
  204.                     fprintf( stderr, "%s: error reading "
  205.                         "line %d of %s\n", basename,
  206.                         nLine, inName ) ;
  207.                     exit( 1 ) ;
  208.                 }
  209.                 if( nLanes < lastNLanes )
  210.                 {
  211.                     addMergeInTrack( nLanes, length ) ;
  212.                 }
  213.                 else
  214.                 {
  215.                     addMergeOutTrack( nLanes, length ) ;
  216.                 }
  217.                 break ;
  218.  
  219.             case L_CURVE_TRACK :
  220.             case R_CURVE_TRACK :
  221.                 if( sscanf( line, "%*s %d %f %f", &nLanes,
  222.                     &angle, &radius ) != 3 )
  223.                 {
  224.                     fprintf( stderr, "%s: error reading "
  225.                         "line %d of %s\n", basename,
  226.                         nLine, inName ) ;
  227.                     exit( 1 ) ;
  228.                 }
  229.                 addCurvedTrack( i, nLanes, angle, radius ) ;
  230.                 break ;
  231.  
  232.             default :
  233.                 fprintf( stderr, "%s: unknown track type at "
  234.                     "line %d of %s\n", basename,
  235.                     nLine, inName ) ;
  236.                 exit( 1 ) ;
  237.                 break ;
  238.         }
  239.     }
  240.  
  241.     myWrite( out, &nTrack, sizeof( nTrack ) ) ;
  242.     myWrite( out, details, sizeof( details[0] ) * ( nTrack + 3 ) / 4 ) ;
  243.  
  244.     printf( "%s contains %d pieces of track (%d maximum)\n", outName,
  245.         nTrack, MAX_COURSE_SIZE ) ;
  246.     fclose( in ) ;
  247.     close( out ) ;
  248. }
  249.  
  250.  
  251.  
  252. /*------------------------------------------------------------------------------
  253.  * Error checking write function.
  254.  *----------------------------------------------------------------------------*/
  255. static void
  256. myWrite(
  257.     int    fd,
  258.     void    *p,
  259.     int    size
  260.     )
  261. {
  262.     if( write( fd, p, size ) != size )
  263.     {
  264.         perror( basename ) ;
  265.         exit( 1 ) ;
  266.     }
  267. }
  268.  
  269.  
  270.  
  271. /*------------------------------------------------------------------------------
  272.  * Add a stretch of straight track.
  273.  *----------------------------------------------------------------------------*/
  274. static void
  275. addStraightTrack(
  276.     int    nLanes,
  277.     float    length
  278.     )
  279. {
  280.     int    ns ;
  281.     float    dl ;
  282.  
  283.     checkLanes( nLanes ) ;
  284.  
  285.     if( length < MINIMAL_STRAIGHT_LENGTH )
  286.     {
  287.         fprintf( stderr, "%s: straight section at line %d too short -- "
  288.                 "must be at least %.1f units\n", basename,
  289.                 nLine, MINIMAL_STRAIGHT_LENGTH ) ;
  290.         exit( 1 ) ;
  291.     }
  292.  
  293.     if( length >= 2.0f * MINIMAL_STRAIGHT_LENGTH )
  294.     {
  295.         ns = (int)( length / OPTIMAL_STRAIGHT_LENGTH + 0.5f ) ;
  296.         dl = length / (float)ns ;
  297.     }
  298.     else
  299.     {
  300.         ns = 1 ;
  301.         dl = length ;
  302.     }
  303.  
  304.     printf( "line %2d: %d straights of length %.1f\n", nLine, ns, dl ) ;
  305.     while( ns-- )
  306.     {
  307.         addTrackToken( STRAIGHT_TRACK, (float)nLanes, dl ) ;
  308.     }
  309.  
  310.     lastNLanes = nLanes ;
  311. }
  312.  
  313.  
  314.  
  315. /*------------------------------------------------------------------------------
  316.  * Add a stretch of merge in track.
  317.  *----------------------------------------------------------------------------*/
  318. static void
  319. addMergeInTrack(
  320.     int    nLanes,
  321.     float    length
  322.     )
  323. {
  324.     int    ns ;
  325.     float    dl ;
  326.  
  327.     checkLanes( nLanes + 2 ) ;
  328.  
  329.     if( length < MINIMAL_STRAIGHT_LENGTH )
  330.     {
  331.         fprintf( stderr, "%s: merge section at line %d too short -- "
  332.                 "must be at least %.1f units\n", basename,
  333.                 nLine, MINIMAL_STRAIGHT_LENGTH ) ;
  334.         exit( 1 ) ;
  335.     }
  336.  
  337.     if( length >= 2.0f * MINIMAL_STRAIGHT_LENGTH )
  338.     {
  339.         ns = (int)( length / OPTIMAL_STRAIGHT_LENGTH + 0.5f ) ;
  340.         dl = length / (float)ns ;
  341.     }
  342.     else
  343.     {
  344.         ns = 1 ;
  345.         dl = length ;
  346.     }
  347.  
  348.     printf( "line %2d: 1 merge-in of length %.1f\n", nLine, dl ) ;
  349.     addTrackToken( MERGE_IN_TRACK, (float)nLanes, dl ) ;
  350.     ns-- ;
  351.  
  352.     if( ns > 0 )
  353.     {
  354.         printf( "line %2d: %d straights-in of length %.1f\n", nLine,
  355.             ns, dl ) ;
  356.         while( ns-- )
  357.         {
  358.             addTrackToken( STRAIGHT_TRACK, (float)nLanes, dl ) ;
  359.         }
  360.     }
  361.  
  362.     lastNLanes = nLanes ;
  363. }
  364.  
  365.  
  366.  
  367. /*------------------------------------------------------------------------------
  368.  * Add a stretch of merge out track.
  369.  *----------------------------------------------------------------------------*/
  370. static void
  371. addMergeOutTrack(
  372.     int    nLanes,
  373.     float    length
  374.     )
  375. {
  376.     int    ns ;
  377.     float    dl ;
  378.  
  379.     checkLanes( nLanes - 2 ) ;
  380.  
  381.     if( length < MINIMAL_STRAIGHT_LENGTH )
  382.     {
  383.         fprintf( stderr, "%s: merge section at line %d too short -- "
  384.                 "must be at least %.1f units\n", basename,
  385.                 nLine, MINIMAL_STRAIGHT_LENGTH ) ;
  386.         exit( 1 ) ;
  387.     }
  388.  
  389.     if( length >= 2.0f * MINIMAL_STRAIGHT_LENGTH )
  390.     {
  391.         ns = (int)( length / OPTIMAL_STRAIGHT_LENGTH + 0.5f ) ;
  392.         dl = length / (float)ns ;
  393.     }
  394.     else
  395.     {
  396.         ns = 1 ;
  397.         dl = length ;
  398.     }
  399.  
  400.     printf( "line %2d: %d merge-outs of length %.1f\n", nLine, ns, dl ) ;
  401.     while( ns-- )
  402.     {
  403.         addTrackToken( MERGE_OUT_TRACK, (float)nLanes, dl ) ;
  404.     }
  405.  
  406.     lastNLanes = nLanes ;
  407. }
  408.  
  409.  
  410.  
  411. /*------------------------------------------------------------------------------
  412.  * Add a stretch of curved track.
  413.  *----------------------------------------------------------------------------*/
  414. static void
  415. addCurvedTrack(
  416.     int    token,
  417.     int    nLanes,
  418.     float    angle,
  419.     float    radius
  420.     )
  421. {
  422.     int    ns ;
  423.     float    da ;
  424.     float    length ;
  425.     float    minRad ;
  426.  
  427.     checkLanes( nLanes ) ;
  428.  
  429.     minRad = radius - 0.5f * ( nLanes - 1 ) * LANE_WIDTH ;
  430.  
  431.     angle = fmodf( angle, 360.0f ) ;
  432.     if( angle <= 0.0f )
  433.     {
  434.         fprintf( stderr, "%s: must specify a curve angle greater than "
  435.             "0.0 (line %d)\n", basename, nLine ) ; 
  436.         exit( 1 ) ;
  437.     }
  438.  
  439.     if( minRad < MIN_RADIUS )
  440.     {
  441.         fprintf( stderr, "%s: curve radius for %d lanes must be %.0f "
  442.             "or greater (line %d)\n", basename, nLanes,
  443.             MIN_RADIUS + 0.5f * ( nLanes - 1 ) * LANE_WIDTH,
  444.             nLine ) ;
  445.         exit( 1 ) ;
  446.     }
  447.  
  448.     length = 2.0f * minRad * angle * M_PI / 180.0f ;
  449.  
  450.     if( length < MINIMAL_STRAIGHT_LENGTH )
  451.     {
  452.         fprintf( stderr, "%s: curve section at line %d too short -- "
  453.                 "must be at least %.1f units\n", basename,
  454.                 nLine, MINIMAL_STRAIGHT_LENGTH ) ;
  455.         exit( 1 ) ;
  456.     }
  457.  
  458.     if( length >= 2.0f * MINIMAL_STRAIGHT_LENGTH )
  459.     {
  460.         ns = (int)( length / OPTIMAL_STRAIGHT_LENGTH + 0.5f ) ;
  461.         da = angle / (float)ns ;
  462.     }
  463.     else
  464.     {
  465.         ns = 1 ;
  466.         da = angle ;
  467.     }
  468.     printf( "line %2d: %d curves of angle %.1f\n", nLine, ns, da ) ;
  469.  
  470.     while( ns-- )
  471.     {
  472.         addTrackToken( token, (float)nLanes * 360.0f + da, radius ) ;
  473.     }
  474.  
  475.     lastNLanes = nLanes ;
  476. }
  477.  
  478.  
  479.  
  480. /*------------------------------------------------------------------------------
  481.  * Check that the number of lanes are correct.
  482.  *----------------------------------------------------------------------------*/
  483. static void
  484. checkLanes(
  485.     int    nLanes
  486.     )
  487. {
  488.     if( nTrack != 0 && nLanes != lastNLanes )
  489.     {
  490.         fprintf( stderr, "%s: bad number of lanes at line %d\n",
  491.             basename, nLine ) ;
  492.         exit( 1 ) ;
  493.     }
  494.  
  495.     if( nLanes != 2 && nLanes != 4 && nLanes != 6 )
  496.     {
  497.         fprintf( stderr, "%s: number of lanes must be 1, 2, 4, or 6 "
  498.             "(line %d)\n", basename, nLine ) ;
  499.         exit( 1 ) ;
  500.     }
  501. }
  502.  
  503.  
  504.  
  505. /*------------------------------------------------------------------------------
  506.  * Add a track token and arguments to the list.
  507.  *----------------------------------------------------------------------------*/
  508. static void
  509. addTrackToken(
  510.     int    token,
  511.     float    arg1,
  512.     float    arg2
  513.     )
  514. {
  515.     int    dp ;
  516.     int    k ;
  517.  
  518.     if( nTrack >= MAX_COURSE_SIZE )
  519.     {
  520.         fprintf( stderr, "%s: course too large by line %d -- reduce "
  521.             "the length\n", basename, nLine ) ;
  522.         exit( 1 ) ;
  523.     }
  524.  
  525.     dp = nTrack / 4 ;
  526.     k = nTrack % 4 ;
  527.     details[dp].id[k] = (char)token ;
  528.     k += k ;
  529.     details[dp].data[k] = arg1 ;
  530.     details[dp].data[k+1] = arg2 ;
  531.  
  532.     nTrack++ ;
  533. }
  534.